package com.ms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ms.constant.GenreTypeConstant;
import com.ms.constant.MessageConstant;
import com.ms.constant.MusicStatusConstant;
import com.ms.context.BaseContext;
import com.ms.domain.dto.MusicUpdateDTO;
import com.ms.domain.dto.MusicUploadDTO;
import com.ms.domain.entity.Album;
import com.ms.domain.entity.Genre;
import com.ms.domain.entity.Music;
import com.ms.domain.entity.User;
import com.ms.exception.BusinessException;
import com.ms.exception.PermissionDeniedException;
import com.ms.exception.ResourceNotFoundException;
import com.ms.mapper.AlbumMapper;
import com.ms.mapper.GenreMapper;
import com.ms.mapper.MusicMapper;
import com.ms.mapper.UserMapper;
import com.ms.service.MusicService;
import com.ms.utiles.OssUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class MusicServiceImpl implements MusicService {
    private final MusicMapper musicMapper;
    private final AlbumMapper albumMapper;
    private final GenreMapper genreMapper;
    private final UserMapper userMapper;
    private final OssUtil ossUtil;

    /**
     * 上传音乐
     * @param dto 音乐信息
     * @param audioFile 音频文件
     * @param coverImage 封面图片
     * @return 音乐实体
     */
    @Override
    public Music uploadMusic(MusicUploadDTO dto, MultipartFile audioFile, MultipartFile coverImage) {
        try {
            log.info("用户{}上传音乐：{}", BaseContext.getCurrentId(), dto);

            // 1. 验证用户
            String[] userIds = dto.getCreatorIds().split("-");
            if (userIds.length == 0) {
                throw new BusinessException(MessageConstant.USER_NOT_FOUND);
            }

            // 2. 验证曲风
            Genre genre = genreMapper.selectById(dto.getGenreId());
            if (genre == null || !"SUBTYPE".equals(genre.getType())) {
                throw new BusinessException(MessageConstant.MUSIC_SELECT_THIRD_LEVEL_GENRE);
            }

            // 3. 验证专辑（如果提供）
            if (dto.getAlbumId() != null) {
                Album album = albumMapper.selectById(dto.getAlbumId());
                if (album == null) {
                    throw new BusinessException(MessageConstant.ALBUM_NOT_FOUND);
                }
                if (!album.getCreatorId().equals(BaseContext.getCurrentId())) {
                    throw new BusinessException(MessageConstant.MUSIC_ONLY_ADD_OWN_ALBUM);
                }
            }

            // 4. 上传文件
            log.info("开始上传音频文件...");
            String audioUrl = ossUtil.uploadFile(audioFile, "audio");
            log.info("音频文件上传成功: {}", audioUrl);

            String coverUrl = null;
            if (coverImage != null) {
                log.info("开始上传封面图片...");
                coverUrl = ossUtil.uploadFile(coverImage, "image");
                log.info("封面图片上传成功: {}", coverUrl);
            }

            // 5. 创建音乐实体
            Music music = Music.builder()
                    .title(dto.getTitle())
                    .fileUrl(audioUrl)
                    .description(dto.getDescription())
                    .coverUrl(coverUrl)
                    .creatorIds(dto.getCreatorIds())
                    .genreId(dto.getGenreId())
                    .albumId(dto.getAlbumId())
                    .status(MusicStatusConstant.PENDING)
                    .build();
            log.info("创建音乐实体: {}", music);

            // 6. 插入数据库
            log.info("开始插入音乐记录...");
            musicMapper.insert(music);
            log.info("音乐记录插入成功，ID: {}", music.getId());

            // 7. 更新专辑封面（如果专辑没有封面）
            if (dto.getAlbumId() != null && coverUrl != null) {
                Album album = albumMapper.selectById(dto.getAlbumId());
                if (StringUtils.isBlank(album.getCoverUrl())) {
                    album.setCoverUrl(coverUrl);
                    albumMapper.updateById(album);
                    log.info("更新专辑封面成功");
                }
            }

            return music;
        } catch (Exception e) {
            log.error("上传音乐过程中出错", e);
            throw new BusinessException(MessageConstant.UPLOAD_FAILED + ": " + e.getMessage());
        }
    }

    /**
     * 获取音乐详情
     * @param id 音乐id
     * @return 音乐实体
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_BY_ID + ':' + #id",
            unless = "#result == null")
    public Music getMusicById(Integer id) {
        Music music = musicMapper.selectById(id);
        if (music == null) {
            throw new ResourceNotFoundException(MessageConstant.MUSIC_NOT_FOUND);
        }

        // 填充关联信息
        fillMusicDetails(music);
        return music;
    }

    /**
     * 分页获取音乐列表
     * @param page 页码
     * @param size 每页数量
     * @return 音乐列表
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE + ':' + #page + ':' + #size",
            unless = "#result == null || #result.records.isEmpty()")
    public Page<Music> getMusicPage(Integer page, Integer size) {
        Page<Music> pageInfo = new Page<>(page, size);
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("status", MusicStatusConstant.APPROVED)
                .orderByDesc("create_time");

        musicMapper.selectPage(pageInfo, query);

        // 填充每条音乐的详细信息
        pageInfo.getRecords().forEach(this::fillMusicDetails);

        return pageInfo;
    }

    /**
     * 根据曲风获取音乐列表
     * @param genreId 曲风id
     * @return 音乐列表
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_GENRE + ':' + #genreId",
            unless = "#result == null || #result.isEmpty()")
    public List<Music> getMusicByGenre(Integer genreId) {
        // 验证曲风是否存在
        Genre genre = genreMapper.selectById(genreId);
        if (genre == null) {
            throw new ResourceNotFoundException(MessageConstant.GENRE_NOT_FOUND);
        }

        // 获取所有相关的曲风ID（包括子曲风）
        List<Integer> relatedGenreIds = getRelatedGenreIds(genreId);
        
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.in("genre_id", relatedGenreIds)
                .eq("status", MusicStatusConstant.APPROVED)
                .orderByDesc("create_time");

        List<Music> musicList = musicMapper.selectList(query);
        musicList.forEach(this::fillMusicDetails);
        return musicList;
    }

    /**
     * 分页获取曲风下的音乐列表
     * @param genreId 曲风id
     * @param page 页码
     * @param size 每页数量
     * @return 音乐列表
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE + ':' + #genreId + ':' + #page + ':' + #size",
            unless = "#result == null || #result.records.isEmpty()")
    public Page<Music> getMusicPageByGenre(Integer genreId, Integer page, Integer size) {
        // 验证曲风是否存在
        Genre genre = genreMapper.selectById(genreId);
        if (genre == null) {
            throw new ResourceNotFoundException(MessageConstant.GENRE_NOT_FOUND);
        }

        // 获取所有相关的曲风ID（包括子曲风）
        List<Integer> relatedGenreIds = getRelatedGenreIds(genreId);
        
        Page<Music> pageInfo = new Page<>(page, size);
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.in("genre_id", relatedGenreIds)
                .eq("status", MusicStatusConstant.APPROVED)
                .orderByDesc("create_time");

        musicMapper.selectPage(pageInfo, query);
        
        // 填充每条音乐的详细信息
        pageInfo.getRecords().forEach(this::fillMusicDetails);
        
        return pageInfo;
    }

    /**
     * 获取指定曲风ID及其所有子曲风的ID列表
     * 支持通过一级或二级曲风ID获取所有相关的三级曲风ID
     * 
     * @param genreId 曲风ID
     * @return 所有相关曲风ID列表
     */
    private List<Integer> getRelatedGenreIds(Integer genreId) {
        List<Integer> genreIds = new ArrayList<>();
        Genre genre = genreMapper.selectById(genreId);
        
        if (genre == null) {
            return genreIds;
        }
        
        // 如果是三级曲风，直接返回
        if (GenreTypeConstant.SUBTYPE.equals(genre.getType())) {
            genreIds.add(genreId);
            return genreIds;
        }
        
        // 如果是一级曲风，查找所有二级和三级子曲风
        if (GenreTypeConstant.MAIN.equals(genre.getType())) {
            // 查找所有二级子曲风
            List<Genre> subGenres = genreMapper.selectList(
                    Wrappers.<Genre>lambdaQuery().eq(Genre::getParentId, genre.getId()).eq(Genre::getType, GenreTypeConstant.SUB)
//                new QueryWrapper<Genre>().eq("parent", genre.getName()).eq("type", "SUB")
            );
            
            // 收集二级曲风的Id
            List<Integer> subGenreIds = subGenres.stream()
                .map(Genre::getId)
                .toList();
            
            if (!subGenreIds.isEmpty()) {
                // 查找所有三级子曲风
                List<Genre> subTypeGenres = genreMapper.selectList(
                        Wrappers.<Genre>lambdaQuery().in(Genre::getParentId, subGenreIds).eq(Genre::getType, GenreTypeConstant.SUBTYPE)
//                    new QueryWrapper<Genre>().in("parent_id", subGenreIds).eq("type", GenreTypeConstant.SUBTYPE)
                );
                
                // 收集三级曲风ID
                List<Integer> subTypeGenreIds = subTypeGenres.stream()
                    .map(Genre::getId)
                    .toList();
                
                genreIds.addAll(subTypeGenreIds);
            }
        }
        
        // 如果是二级曲风，查找所有三级子曲风
        if (GenreTypeConstant.SUB.equals(genre.getType())) {
            List<Genre> subTypeGenres = genreMapper.selectList(
                    Wrappers.<Genre>lambdaQuery().eq(Genre::getParentId, genre.getId()).eq(Genre::getType, GenreTypeConstant.SUBTYPE)
//                new QueryWrapper<Genre>().eq("parent", genre.getName()).eq("type", "SUBTYPE")
            );
            
            // 收集三级曲风ID
            List<Integer> subTypeGenreIds = subTypeGenres.stream()
                .map(Genre::getId)
                .toList();
            
            genreIds.addAll(subTypeGenreIds);
        }
        
        // 如果没有找到子曲风，但仍需要包含当前曲风（如果它是三级曲风）
        if (genreIds.isEmpty() && GenreTypeConstant.SUBTYPE.equals(genre.getType())) {
            genreIds.add(genreId);
        }
        
        return genreIds;
    }

    /**
     * 获取用户上传的音乐
     * @param userId 用户id
     * @return 用户上传的音乐列表
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_USER + ':' + #userId",
            unless = "#result == null || #result.isEmpty()")
//    public List<Music> getUserMusic(Integer userId) {
//        // 验证用户是否存在
//        if (userMapper.selectById(userId) == null) {
//            throw new ResourceNotFoundException(MessageConstant.USER_NOT_FOUND);
//        }
//
//        // 获取所有音乐并手动过滤
//        List<Music> allMusicList = musicMapper.selectList(new QueryWrapper<Music>().orderByDesc("create_time"));
//        List<Music> result = new ArrayList<>();
//
//        for (Music music : allMusicList) {
//            if (music.getCreatorIds() != null &&
//                Arrays.asList(music.getCreatorIds().split("-")).contains(userId.toString())) {
//                result.add(music);
//            }
//        }
//
//        result.forEach(this::fillMusicDetails);
//        return result;
//    }
    public List<Music> getUserMusic(Integer userId) {
        // 使用SQL直接查询
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.like("creator_ids", userId) // 使用LIKE匹配包含用户ID
                .eq("status", MusicStatusConstant.APPROVED)
                .orderByDesc("create_time");

        List<Music> result = musicMapper.selectList(query);
        result.forEach(this::fillMusicDetails);
        return result;
    }

    /**
     * 获取用户上传的音乐分页
     * @param userId 用户id
     * @param page 页码
     * @param size 每页数量
     * @return 用户上传的音乐分页
     */
    @Override
    @Cacheable(value = "music",
            key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE + ':' + #userId + ':' + #page + ':' + #size",
            unless = "#result == null")
    public Page<Music> getUserMusicPage(Integer userId, Integer page, Integer size) {
        // 验证用户是否存在
        if (userMapper.selectById(userId) == null) {
            throw new ResourceNotFoundException(MessageConstant.USER_NOT_FOUND);
        }

        Page<Music> pageInfo = new Page<>(page, size);
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("creator_id", userId)
                .orderByDesc("create_time");

        musicMapper.selectPage(pageInfo, query);
        pageInfo.getRecords().forEach(this::fillMusicDetails);
        return pageInfo;
    }

    /**
     * 更新音乐
     * @param dto 音乐更新信息
     */
    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = "music", key = "#dto.id", beforeInvocation = true),
            @CacheEvict(value = "music", key = "'list:' + #dto.genreId", beforeInvocation = true),
            @CacheEvict(value = "music", key = "'page:' + '*'", beforeInvocation = true)
    })
    public void updateMusic(MusicUpdateDTO dto) {
        Music music = musicMapper.selectById(dto.getId());
        if (music == null) {
            throw new ResourceNotFoundException(MessageConstant.MUSIC_NOT_FOUND);
        }

        // 权限检查：只能修改自己的音乐
        String[] userIds = dto.getCreatorIds().split("-");
        if (userIds.length == 0) {
            throw new BusinessException(MessageConstant.USER_NOT_FOUND);
        }

        // 检查状态：已审核的音乐不能修改
        if (MusicStatusConstant.APPROVED.equals(music.getStatus())) {
            throw new BusinessException(MessageConstant.MUSIC_APPROVED_CANNOT_MODIFY);
        }

        // 更新基本信息
        Music updateEntity = new Music();
        updateEntity.setId(dto.getId());
        updateEntity.setTitle(dto.getTitle());
        updateEntity.setDescription(dto.getDescription());

        // 更新专辑
        if (dto.getAlbumId() != null && !dto.getAlbumId().equals(music.getAlbumId())) {
            Album album = albumMapper.selectById(dto.getAlbumId());
            if (album == null) {
                throw new BusinessException(MessageConstant.ALBUM_NOT_FOUND);
            }
            if (!album.getCreatorId().equals(BaseContext.getCurrentId())) {
                throw new PermissionDeniedException(MessageConstant.MUSIC_ONLY_ADD_OWN_ALBUM);
            }
            updateEntity.setAlbumId(dto.getAlbumId());
        }

        // 更新曲风
        if (dto.getGenreId() != null && !dto.getGenreId().equals(music.getGenreId())) {
            Genre genre = genreMapper.selectById(dto.getGenreId());
            if (genre == null || !GenreTypeConstant.SUBTYPE.equals(genre.getType())) {
                throw new BusinessException(MessageConstant.MUSIC_SELECT_THIRD_LEVEL_GENRE);
            }
            updateEntity.setGenreId(dto.getGenreId());
        }

        musicMapper.updateById(updateEntity);
    }

    /**
     * 删除音乐
     * @param id 音乐id
     */
    @Override
    @Transactional
    @CacheEvict(value = "music", allEntries = true, beforeInvocation = true)
    public void deleteMusic(Integer id) {
        Music music = musicMapper.selectById(id);
        if (music == null) throw new ResourceNotFoundException(MessageConstant.MUSIC_NOT_FOUND);

        // 权限检查：只能删除自己的音乐
        String[] userIds = music.getCreatorIds().split("-");
        if (userIds.length == 0) {
            throw new BusinessException(MessageConstant.USER_NOT_FOUND);
        }

        // 删除OSS文件
        ossUtil.deleteFile(music.getFileUrl());
        ossUtil.deleteFile(music.getCoverUrl());

        // 删除数据库记录
        musicMapper.deleteById(id);
    }

    /**
     * 填充音乐的详细信息
     */
    private void fillMusicDetails(Music music) {
        // 填充创建者名称
        String[] userIds = music.getCreatorIds().split("-");
        List<User> creators = userMapper.selectByIds(Arrays.asList(userIds));
        if (creators != null) {
            List<String> creatorNames = creators.stream()
                .map(User::getUsername)
                .toList();
            music.setCreatorName(creatorNames);
        }

        // 填充曲风名称
        Genre genre = genreMapper.selectById(music.getGenreId());
        if (genre != null) {
            music.setGenreName(genre.getName());
        }

        // 填充专辑名称
        if (music.getAlbumId() != null) {
            Album album = albumMapper.selectById(music.getAlbumId());
            if (album != null) {
                music.setAlbumTitle(album.getTitle());
            }
        }
    }
}